
#include "lcd_init.h"
#include <systick.h>
#include "gd32f4xx_timer.h"


#define RS_PORT                 GPIOA
#define RS_PIN                  GPIO_PIN_9

#define CS_PORT                 GPIOC
#define CS_PIN                  GPIO_PIN_11
#define RST_PORT                GPIOA
#define RST_PIN                 GPIO_PIN_15
               


#define  SPI_LCD_RS_LOW()        gpio_bit_reset(RS_PORT, RS_PIN);
#define  SPI_LCD_RS_HIGH()       gpio_bit_set(RS_PORT, RS_PIN);

#define  SPI_LCD_CS_HIGH()       gpio_bit_set(CS_PORT, CS_PIN);
#define  SPI_LCD_CS_LOW()        gpio_bit_reset(CS_PORT, CS_PIN);

#define  SPI_LCD_RST_LOW()        gpio_bit_reset(RST_PORT, RST_PIN);
#define  SPI_LCD_RST_HIGH()       gpio_bit_set(RST_PORT, RST_PIN);

#define DMAx            DMA1
#define DMA_CHx         DMA_CH4
#define SPIx            SPI3
#define DMA_SUBPERIx    DMA_SUBPERI5


#if DAPLINK_IF
    #include "sys_setup.h"
#endif
//ok
/******************************************************************************
******************************************************************************/
void LCD_WR_DATA8(uint8_t dat)
{
    LCD_Write_Bus(dat);
}


/******************************************************************************
******************************************************************************/
void LCD_WR_DATA(uint16_t dat)
{
    LCD_Write_Bus(dat >> 8);
    LCD_Write_Bus(dat);

}


/******************************************************************************
******************************************************************************/
void LCD_WR_REG(uint8_t dat)
{
    SPI_LCD_RS_LOW();
    LCD_Write_Bus(dat);
    SPI_LCD_RS_HIGH();
}


/******************************************************************************
******************************************************************************/
void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    LCD_WR_REG(0x2a);
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);
}

void LCD_InitDir()
{
    #if DAPLINK_IF
 
    LCD_WR_REG(0X36);// Memory Access Control

    if(sys_setup_get()->image_flip == 0)
    {
        LCD_WR_DATA8(0x70);
    }
    else
    {
        LCD_WR_DATA8(0xA0);
    }

    #else
    LCD_WR_REG(0X36);// Memory Access Control
    LCD_WR_DATA8(0x70);
    #endif
}

void ST7789S_Init()
{
    SPI_LCD_CS_LOW();
    //************* Start Initial Sequence **********//
    LCD_WR_REG(0x11);	//
    delay_1ms(100); 		//Delay 120ms

    LCD_InitDir();

    LCD_WR_REG(0X3A);//
    LCD_WR_DATA8(0X05);
    //--------------------------------ST7789S Frame rate setting-------------------------

    LCD_WR_REG(0xb2);    //Porch Setting
    LCD_WR_DATA8(0x0c);
    LCD_WR_DATA8(0x0c);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x33);
    LCD_WR_REG(0xb7);    //Gate Control
    LCD_WR_DATA8(0x35);
    //---------------------------------ST7789S Power setting-----------------------------

    LCD_WR_REG(0xbb);     //VCOM Setting
    LCD_WR_DATA8(0x35);
    LCD_WR_REG(0xc0);      //LCM Control
    LCD_WR_DATA8(0x2c);
    LCD_WR_REG(0xc2);
    LCD_WR_DATA8(0x01);
    LCD_WR_REG(0xc3);      //VRH Set
    LCD_WR_DATA8(0x13);
    LCD_WR_REG(0xc4);
    LCD_WR_DATA8(0x20);
    LCD_WR_REG(0xc6);
    LCD_WR_DATA8(0x0f);
    LCD_WR_REG(0xca);
    LCD_WR_DATA8(0x0f);
    LCD_WR_REG(0xc8);
    LCD_WR_DATA8(0x08);
    LCD_WR_REG(0x55);
    LCD_WR_DATA8(0x90);
    LCD_WR_REG(0xd0);
    LCD_WR_DATA8(0xa4);
    LCD_WR_DATA8(0xa1);
    //--------------------------------ST7789S gamma setting------------------------------
    LCD_WR_REG(0xe0);    // Positive Voltage Gamma Control
    LCD_WR_DATA8(0xd0);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x06);
    LCD_WR_DATA8(0x09);
    LCD_WR_DATA8(0x0b);
    LCD_WR_DATA8(0x2a);
    LCD_WR_DATA8(0x3c);
    LCD_WR_DATA8(0x55);
    LCD_WR_DATA8(0x4b);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x14);
    LCD_WR_DATA8(0x19);
    LCD_WR_DATA8(0x20);
    LCD_WR_REG(0xe1);     // Negative Voltage Gamma Control
    LCD_WR_DATA8(0xd0);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x06);
    LCD_WR_DATA8(0x09);
    LCD_WR_DATA8(0x0b);
    LCD_WR_DATA8(0x29);
    LCD_WR_DATA8(0x36);
    LCD_WR_DATA8(0x54);
    LCD_WR_DATA8(0x4b);
    LCD_WR_DATA8(0x0d);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x14);
    LCD_WR_DATA8(0x21);
    LCD_WR_DATA8(0x20);

}


void ST7789V2_Init()
{
    SPI_LCD_RST_LOW();
    delay_1ms(100);
    SPI_LCD_RST_HIGH();
    delay_1ms(100);

    SPI_LCD_CS_LOW();
    //************* Start Initial Sequence **********//
    LCD_WR_REG(0x11);//
    delay_1ms(100); //Delay 120ms
    //LCD_WR_REG(0X36);// Memory Access Control

    LCD_InitDir();

    LCD_WR_REG(0x3A);
    LCD_WR_DATA8(0x05);  // 5: RGB565     6: RGB666

    LCD_WR_REG(0xB2);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x33);

    LCD_WR_REG(0xB7);
    LCD_WR_DATA8(0x71);   //VGH=14.97V,VGL=-7.67V

    LCD_WR_REG(0xBB);
    LCD_WR_DATA8(0x1F);

    LCD_WR_REG(0xC0);
    LCD_WR_DATA8(0x2C);

    LCD_WR_REG(0xC2);
    LCD_WR_DATA8(0x01);

    LCD_WR_REG(0xC3);
    LCD_WR_DATA8(0x10);

    LCD_WR_REG(0xC4);
    LCD_WR_DATA8(0x20);

    LCD_WR_REG(0xC6);
    LCD_WR_DATA8(0x0F);

    LCD_WR_REG(0xD0);
    LCD_WR_DATA8(0xA4);
    LCD_WR_DATA8(0xA1);

    LCD_WR_REG(0xD6);
    LCD_WR_DATA8(0xA1);

    LCD_WR_REG(0xE0);
    LCD_WR_DATA8(0xD0);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x0E);
    LCD_WR_DATA8(0x0B);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0x14);
    LCD_WR_DATA8(0x38);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x4F);
    LCD_WR_DATA8(0x37);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x2A);
    LCD_WR_DATA8(0x2E);

    LCD_WR_REG(0xE1);
    LCD_WR_DATA8(0xD0);
    LCD_WR_DATA8(0x0B);
    LCD_WR_DATA8(0x10);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x06);
    LCD_WR_DATA8(0x35);
    LCD_WR_DATA8(0x54);
    LCD_WR_DATA8(0x4D);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0x14);
    LCD_WR_DATA8(0x14);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x2F);

    LCD_WR_REG(0xE9);      // Equalize time control
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x03);

    LCD_WR_REG(0x21);   //Display Inversion On  ����
}


void Sais_Init()
{
    SPI_LCD_CS_LOW();

    SPI_LCD_RST_HIGH();
    delay_1us(10);
    SPI_LCD_RST_LOW();
    delay_1ms(20);
    SPI_LCD_RST_HIGH();
    delay_1ms(20);

    LCD_WR_REG(0x11);
    delay_1ms(20);

    LCD_WR_REG(0xCF);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0xc1);
    LCD_WR_DATA8(0x30);

    LCD_WR_REG(0xED);
    LCD_WR_DATA8(0x64);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0x12);
    LCD_WR_DATA8(0x81);

    LCD_WR_REG(0xE8);
    LCD_WR_DATA8(0x85);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x79);

    LCD_WR_REG(0xCB);
    LCD_WR_DATA8(0x39);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x34);
    LCD_WR_DATA8(0x02);

    LCD_WR_REG(0xF7);
    LCD_WR_DATA8(0x20);

    LCD_WR_REG(0xEA);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x00);

    LCD_WR_REG(0xC0);
    LCD_WR_DATA8(0x16);

    LCD_WR_REG(0xC1);
    LCD_WR_DATA8(0x11);

    LCD_WR_REG(0xC5);
    LCD_WR_DATA8(0x2B);//vcomh
    LCD_WR_DATA8(0x2C);//vcoml

    LCD_WR_REG(0xC7);
    LCD_WR_DATA8(0xC0);
    LCD_WR_REG(0xB1);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x1B);

    LCD_WR_REG(0xB6);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0xA2);

    LCD_WR_REG(0xB4);
    LCD_WR_DATA8(0x00);
////////RGB interface setting/////////
    LCD_WR_REG(0xB0);
    LCD_WR_DATA8(0xc0); //0x40 DE mode, 0x60 sync mode

    LCD_WR_REG(0xF6);
    LCD_WR_DATA8(0X01);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0X06);
    /*
    LCD_WR_REG(0xb5);
    Write_Data(FPS);
    Write_Data(VPS);
    Write_Data(LPS);
    Write_Data(HPS);
    */
//////////////////////////////////////////////
    LCD_WR_REG(0xF2);
    LCD_WR_DATA8(0x00);

    LCD_WR_REG(0x26);
    LCD_WR_DATA8(0x01);

    LCD_WR_REG(0x36);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0x3a);
    LCD_WR_DATA8(0x05);  /// 16bit

    LCD_InitDir();
    LCD_WR_REG(0x21); //ips

    LCD_WR_REG(0xb2);
    LCD_WR_DATA8(0x0c);
    LCD_WR_DATA8(0x0c);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x33);

    LCD_WR_REG(0xb7);
    LCD_WR_DATA8(0x35);

    LCD_WR_REG(0xbb);
    LCD_WR_DATA8(0x21);
    LCD_WR_REG(0xc0);
    LCD_WR_DATA8(0x2c);
    LCD_WR_REG(0xc2);
    LCD_WR_DATA8(0x01);
    LCD_WR_REG(0xc3);
    LCD_WR_DATA8(0x0b);
    LCD_WR_REG(0xc4);
    LCD_WR_DATA8(0x20);
    LCD_WR_REG(0xc6);
    LCD_WR_DATA8(0x0f);
    LCD_WR_REG(0xd0);
    LCD_WR_DATA8(0xa4);
    LCD_WR_DATA8(0xa1);

    LCD_WR_REG(0xE0);       //Set Gamma
    LCD_WR_DATA8(0x0F);
    LCD_WR_DATA8(0x29);
    LCD_WR_DATA8(0x24);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x0E);
    LCD_WR_DATA8(0x09);
    LCD_WR_DATA8(0x4E);
    LCD_WR_DATA8(0x78);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x09);
    LCD_WR_DATA8(0x13);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x17);
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x00);

    LCD_WR_REG(0XE1);       //Set Gamma
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x1B);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x31);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x42);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0x28);
    LCD_WR_DATA8(0x2F);
    LCD_WR_DATA8(0x0F);

}



void LCD_Init(void)
{
    Init_Spi();
	  
    ST7789V2_Init();
}

void LCD_SetBrightness(uint8_t duty)
{
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, duty);
}


void LCD_DisplayOn()
{
    LCD_WR_REG(0x29);
}





// 延迟函数，产生1微秒的延迟
void delay_1us(uint32_t count) {
    uint32_t i;
    for (i = 0; i < count; i++) {
        // 根据MCU的频率调整这个循环次数以产生1微秒的延迟
        // 这个值需要根据实际的MCU主频进行校准
        __NOP(); // 一个占位的无操作指令
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
    }
}
	


// SPI发送数据函数
void LCD_Write_Bus(uint8_t data) {
    
    // 拉低片选信号
    SPI_LCD_CS_LOW();

    while (RESET == spi_i2s_flag_get(SPIx, SPI_FLAG_TBE)) {
    }

    spi_i2s_data_transmit(SPIx, data);

    while (RESET == spi_i2s_flag_get(SPIx, SPI_FLAG_RBNE)) {}
    spi_i2s_data_receive(SPIx);
    (void)SPI_STAT(SPIx);

    // 拉高片选信号
    SPI_LCD_CS_HIGH();
}



// SPI DMA发送数据函数
void bs_lcd_dma_transmit(uint8_t *data, uint16_t size) {
    dma_single_data_parameter_struct dma_init_struct;

    // 启用DMA时钟
    // rcu_periph_clock_enable(RCU_DMA0);


	//dma_channel_disable(DMAx, DMA_CHx); // 禁用DMA通道
    dma_deinit(DMAx, DMA_CHx); // 重置DMA通道

    dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
    dma_init_struct.memory0_addr = (uint32_t)data;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.number =  size;
    dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPIx);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;

    dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE;
    dma_single_data_mode_init(DMAx, DMA_CHx, &dma_init_struct);
    dma_channel_subperipheral_select(DMAx, DMA_CHx, DMA_SUBPERIx);
    /* configure DMA mode */
    dma_circulation_disable(DMAx, DMA_CHx);
	
	

    // 启用DMA传输完成中断
    dma_interrupt_flag_clear(DMAx, DMA_CHx, DMA_INT_FLAG_FTF);
    // dma_interrupt_enable(DMAx, DMA_CHx, DMA_INT_FTF);

    // 拉低片选信号
    SPI_LCD_CS_LOW();

    // 启用DMA传输
    dma_channel_enable(DMAx, DMA_CHx);

    // 启用SPI的DMA传输
    spi_dma_enable(SPIx, SPI_DMA_TRANSMIT);

    // 等待DMA传输完成
    while (!dma_flag_get(DMAx, DMA_CHx, DMA_FLAG_FTF)) {
    }

    while (SET == spi_i2s_flag_get(SPIx, SPI_FLAG_TRANS)) {
    }

    spi_i2s_data_receive(SPIx);
    (void)SPI_STAT(SPIx);
    // 禁用DMA传输
    dma_channel_disable(DMAx, DMA_CHx);
    spi_dma_disable(SPIx, SPI_DMA_TRANSMIT);

    // 拉高片选信号
    SPI_LCD_CS_HIGH();
}



// SPI初始化函数
void Init_Spi(void) {
    // Enable clocks
    rcu_periph_clock_enable(RCU_SPI3);

    // Configure SPI pins: PD3->SCK, PC1->MOSI
    gpio_af_set(GPIOE, GPIO_AF_5, GPIO_PIN_2); // SCK
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
    
    gpio_af_set(GPIOE, GPIO_AF_5, GPIO_PIN_6); // MOSI
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);

    // Configure chip select, RS, and RST pins: PD1->CS, PF1->RS, PF2->RST
    gpio_mode_set(RS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RS_PIN); // RS
    gpio_output_options_set(RS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RS_PIN);

    gpio_mode_set(CS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CS_PIN); // CS
    gpio_output_options_set(CS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CS_PIN);

    gpio_mode_set(RST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RST_PIN); // RST
    gpio_output_options_set(RST_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RST_PIN);

    SPI_LCD_CS_HIGH(); // CS default high
    SPI_LCD_RS_HIGH(); // RS default high
    SPI_LCD_RST_HIGH(); // RST default high

    spi_i2s_deinit(SPIx);
    // SPI parameter settings
    spi_parameter_struct spi_init_struct;
    spi_struct_para_init(&spi_init_struct);
		
    spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode = SPI_MASTER;
    spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;
    spi_init_struct.nss = SPI_NSS_SOFT;
    spi_init_struct.prescale = SPI_PSC_16;
    spi_init_struct.endian = SPI_ENDIAN_MSB;

    spi_init(SPIx, &spi_init_struct);
    spi_enable(SPIx);
}



















